package com.sync.utils.project.demo.controller;

import cn.hutool.core.bean.BeanUtil;
import com.sync.utils.common.constant.HeaderConstants;
import com.sync.utils.common.utils.TokenUtils;
import com.sync.utils.common.validation.Groups;
import com.sync.utils.framework.entity.AppInfo;
import com.sync.utils.framework.redis.entity.Message;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.sync.utils.common.base.controller.impl.BaseControllerImpl;
import com.sync.utils.project.demo.mapper.JokeMapper;
import com.sync.utils.project.demo.pojo.*;
import com.sync.utils.framework.result.R;
import com.sync.utils.project.demo.service.AppService;
import com.sync.utils.project.demo.service.JokeService;
import com.sync.utils.project.demo.service.UserService;


import com.sync.utils.common.annotation.Log;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.groups.Default;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Validated
@RestController
@RequestMapping("/user/")
public class UserController extends BaseControllerImpl {

    @Autowired
    private UserService userService;

    @Autowired
    private JokeService jokeService;

    @Autowired
    private JokeMapper jokeMapper;

    @Autowired
    private AppService appService;

    @Autowired
    private Validator validator;


    @GetMapping(value = "getByAccount")
    public R<UserInfo> getByAccount(@RequestParam("account") String account){
        UserInfo user = userService.getByAccount(account);
        return R.ok().data(user);
    }

    @RequestMapping(value = "getUserList",method = {RequestMethod.GET,RequestMethod.POST})
    public R getUserList(@RequestBody UserReq userReq){
        PageView<UserDto> page = userService.getUserList(userReq);
        log.info("userList",page);
        return R.ok().data(page);
    }

    /**
     * TODO
     *
     * @Author YWF
     * @Date  2023/7/27 15:23
     * @Param
     **/
    @GetMapping(value = "getUser")
    public R<UserRes> getUser(@RequestParam("userId") String userId){
        log.info("用户信息","用户信息查询");
        return R.ok().data(userService.getUser(userId));
    }


    @Log("用户信息修改")
    @PostMapping(value = "updateUserById")
    public R<UserRes> updateUserById(@RequestBody UserVo userVo){
        return R.ok().data(userService.updateUserById(userVo));
    }

    @Log("用户信息删除")
    @PostMapping(value = "deleteUser")
    public R deleteUser(@RequestParam("userIds") String[] userIds){
        List<String> collectIds = Arrays.stream(userIds).collect(Collectors.toList());
        if (collectIds.contains("10000")){
            return R.error().message("管理员不能被删除");
        }
        int counts = userService.deleteUser(collectIds);
        if (counts>0){
            return R.ok().data("成功删除"+counts+"个用户");
        }
        return R.error().message("用户删除失败");
    }

    @PostMapping(value = "/saveUser")
    public R saveUser(@RequestBody @Validated(Groups.Create.class) UserReq userReq){
        UserVo userVo = BeanUtil.copyProperties(userReq,UserVo.class);
        int counts = userService.saveUser(userVo);
        if (counts>0){
            return R.ok().message("用户保存成功");
        }
        return R.error().message("用户保存失败");
    }

    /**
     * 编程式校验数据
     * @param userReq
     * @return
     */
    @PostMapping(value = "/updateUser")
    public R updateUser(@RequestBody UserReq userReq){
        Set<ConstraintViolation<UserReq>> validate = validator.validate(userReq, Groups.Update.class);
        if (validate.isEmpty()){
            logger.info("校验通过，执行业务逻辑");
        }else {
            logger.info("校验失败，执行异常业务逻辑");
        }
        return R.ok().data(userReq);
    }

    @GetMapping(value = "getUsers")
    public R getUser(@RequestParam @Max(value = 99, message = "年龄不能大于99岁") Integer age,
                     @RequestParam @Min(value = 1, message = "页码必须大于0") Integer page,
                     @RequestParam @Range(min = 1, max = 100, message = "每页数量必须在1-100之间") Integer size){
        UserInfo user = new UserInfo();
        user.setUserId(Optional.ofNullable(age).map(Integer::longValue).orElse(0L));
        return R.ok().data(user);
    }

    @RequestMapping(value = "getCityWeather",method = {RequestMethod.GET})
    public R getCityWeather(@RequestParam("city") String city){
        WeatherVo weatherVo = null;
        JHApiResult jhApiResult = userService.getCityWeather(city);
        if (jhApiResult!=null && jhApiResult.getErrorCode().equals("0")){
            weatherVo = JSON.parseObject(jhApiResult.getResult(),WeatherVo.class);
            log.info("weatherVo:"+weatherVo);
            return R.ok().data(weatherVo);
        }
        return R.error().code(-20056).message(jhApiResult.getReason());
    }

    @Log("获取新闻信息")
    @RequestMapping(value = "getNews",method = {RequestMethod.GET,RequestMethod.POST})
    public R getNews(@RequestParam("page") Integer page,@RequestParam("pageSize") Integer pageSize){
        JHApiResult jhApiResult = userService.getNews(request,page,pageSize);
        if (jhApiResult != null && jhApiResult.getErrorCode().equals("0")){
            NewsVo newsVo = JSON.parseObject(jhApiResult.getResult(), NewsVo.class);
            if (newsVo.getStat().equals("1")){
                List<NewsInfo> newsList = newsVo.getData();
                return R.ok().data(newsList);
            }
        }
        return R.error().code(-20057).message(jhApiResult.getReason());
    }

    @GetMapping(value = "getJokes")
    public R getJokes(@Param("page") Integer page,@Param("pageSize") Integer pageSize){
        JHApiResult jhApiResult = userService.getJokes(request,page,pageSize);
        if (jhApiResult!=null && jhApiResult.getErrorCode().equals("0")){
            JSONObject result = JSON.parseObject(jhApiResult.getResult());
            if (result!=null){
                List<JokeVo> jokeVoList = JSON.parseArray(result.getString("data"),JokeVo.class);
                log.info("jokeVoList:"+jokeVoList);
                return R.ok().data(jokeVoList);
            }
        }
        return R.error().code(-20058).message(jhApiResult.getReason());
    }

    @GetMapping(value = "sendSimpleMail")
    public R sendSimpleMail(){
        mailService.sendSimpleMail(new String[]{"737376332@qq.com"},"测试邮件","哈哈哈哈");
        return R.ok().data("邮件发送成功");
    }

    @GetMapping(value = "sendMail")
    public R sendMail(HttpServletRequest request) throws MessagingException {
        JHApiResult jhApiResult = userService.getJokes(request,1,3);
        if (jhApiResult!=null && jhApiResult.getErrorCode().equals("0")){
            JSONObject result = JSON.parseObject(jhApiResult.getResult());
            if (result!=null){
                List<JokeVo> jokeVoList = JSON.parseArray(result.getString("data"),JokeVo.class);
                for (JokeVo jokeVo : jokeVoList) {
                    String jokeCont = jokeVo.getContent();
                    mailService.sendSimpleMail(new String[]{"737376332@qq.com"},"笑话",jokeCont);
                }
                log.info("jokeVoList:"+jokeVoList);
                return R.ok().data(jokeVoList);
            }
        }
        return R.ok().data("邮件发送成功");
    }


    @GetMapping(value = "getJokeList")
    public R<IPage<JokeDto>> getJokeList(@Param("page") Integer page,@Param("pageSize") Integer pageSize){
        IPage<JokeDto> ipage = jokeService.getJokeIPage(this.getRequest(),page,pageSize);
        return R.ok().data(ipage);
    }

    @GetMapping(value = "saveJokeForNet")
    public R saveJokeForNet(){

        logger.trace("*****************trace**********");
        logger.debug("*************debug*************");
        logger.info("**************info****************");
        logger.warn("****************warn***************");
        logger.error("****************error*************");
        mailService.sendSimpleMail(new String[]{"737376332@qq.com"},"测试邮件","哈哈哈哈");
        //logger.info("param：{}",getIntParam("name"));
        //logger.info("name：{}",requireIntParam("name"));
        int total = jokeService.saveJokeForNet();
        return R.ok().data(total);
    }

    @GetMapping(value = "getRedisList")
    public R getRedisList(@RequestParam("type") Integer type){
        switch (type){
            case 1:
                /*测试LIst集合存储*/
                redisCache.delete("jokeList");
                List<JokeDto> allList = new ArrayList<>();
                JokeDto joke = new JokeDto();
                joke.setHashId("007C074B79B240D");
                joke.setContent("妻子想买件衣服，丈夫陪她一起上街");
                joke.setUnixtime(1418745228);
                joke.setUpdatetime("2014-12-16 23:53:48");
                JokeDto joke1 = new JokeDto();
                joke1.setHashId("1164C1DCD5D6");
                joke1.setContent("下班后，老公到车站接老婆。");
                joke1.setUnixtime(1418745228);
                joke1.setUpdatetime("2015-12-16 23:53:48");
                allList.add(joke);
                allList.add(joke1);
                redisCache.lSet("jokeList",allList);
                List<JokeDto> list = redisCache.lGet("jokeList",0,0);
                logger.info("试LIst集合存储");
                return R.ok().data(list);
            case 2:
                /*测试对象的存储*/
                JokeDto joke2 = new JokeDto();
                joke2.setHashId("007C074B79B240D");
                joke2.setContent("妻子想买件衣服，丈夫陪她一起上街");
                joke2.setUnixtime(1418745228);
                joke2.setUpdatetime("2014-12-16 23:53:48");
                redisCache.set("jokeList::object",joke2);
                JokeDto ob = redisCache.get("jokeList::object");
                logger.info("测试对象的存储");
                return R.ok().data(ob);
            case 3:
                /*测试字符串*/
                redisCache.set("aaa",213);
                Integer result = redisCache.get("aaa");
                logger.info("测试字符串存储");
                return R.ok().data(result);
            case 4:
                /*测试hash对象*/
                Map<String,Object> map = new HashMap<>();
                JokeDto joke3 = new JokeDto();
                joke3.setHashId("007C074B79B240D");
                joke3.setContent("妻子想买件衣服，丈夫陪她一起上街");
                joke3.setUnixtime(1418745228);
                joke3.setUpdatetime("2014-12-16 23:53:48");
                UserInfo user = new UserInfo();
                user.setUserId(10000L);
                user.setName("打张飞");
                user.setEmail("7373737@qqq.com");
                user.setCreateTime(new Date());
                map.put("joke3",joke3);
                map.put("user",user);
                redisCache.hmset("map:object",map);
                UserInfo user2 = new UserInfo();
                user2.setUserId(9999L);
                redisCache.hset("map:object","user",user2);
                Map<String,JokeDto> res = redisCache.hmget("map:object");
                UserInfo user1 = redisCache.hget("map:object","user");
                return R.ok().data(res);
            case 5:
                JokeDto joke4 = new JokeDto();
                joke4.setHashId("007C074B79B240D");
                joke4.setContent("妻子想买件衣服，丈夫陪她一起上街");
                joke4.setUnixtime(1418745228);
                joke4.setUpdatetime("2014-12-16 23:53:48");

                UserInfo user3 = new UserInfo();
                user3.setUserId(10000L);
                user3.setName("打张飞");
                user3.setEmail("7373737@qqq.com");
                user3.setCreateTime(new Date());

                redisCache.sSet("set:object",joke4,user3);
                Set<JokeDto> s = redisCache.sGet("set:object");
                return R.ok().data(s);
            case 6:
                redisCache.zsetSet("user","张三",90);
                redisCache.zsetSet("user","李四",95);
                redisCache.zsetSet("user","王五",70);
                redisCache.zsetSet("user","赵刘",20);
                Set<String> rs = redisCache.zsetRange("user", 0, -1);
                Set<ZSetOperations.TypedTuple<String>> rs1 = redisCache.zsetRangeWithScore("user", 0, -1);
                Set<ZSetOperations.TypedTuple<Object>> rs2 = redisTemplate.opsForZSet().reverseRangeWithScores("user", 0, -1);
                return R.ok().data(rs2);
            default:
                break;
        }
        return R.ok();
    }

    /**
     * 测试redis排行榜
     * @return
     */
    @GetMapping(value = "getJokeRanking")
    public R getJokeRanking(){
        final String redisKey = "joke:ranking";
        List<JokeDto> jokeList = jokeMapper.selectList(null);
        if (CollectionUtil.isNotEmpty(jokeList)){
            Set<ZSetOperations.TypedTuple<JokeVo>> tuples = new HashSet<>();
            for (JokeDto jokeDto : jokeList) {
                JokeVo jokeVo = BeanUtil.copyProperties(jokeDto,JokeVo.class);
                DefaultTypedTuple<JokeVo> tuple = new DefaultTypedTuple<>(jokeVo,jokeDto.getScore());
                tuples.add(tuple);
            }
            redisTemplate.opsForZSet().add(redisKey,tuples);
        }
        Set<ZSetOperations.TypedTuple<String>> rs = redisCache.zsetReverseWithScores(redisKey, 0, 5);
        return R.ok().data(rs);
    }

    @GetMapping(value = "getJokeForNet")
    public R getJokeForNet(){
        JHApiResult jhApiResult = jokeService.getJokeForNet();
        if (jhApiResult != null && jhApiResult.getErrorCode().equals("0")){
            NewsVo newsVo = JSON.parseObject(jhApiResult.getResult(), NewsVo.class);
            if (newsVo.getStat().equals("1")){
                List<NewsInfo> newsList = newsVo.getData();
                return R.ok().data(newsList);
            }
        }
        return R.error().code(-20057).message(jhApiResult.getReason());
    }

    private final static String CHANNEL = "public_topic";

    //@PassToken
    @GetMapping(value = "redisPublish")
    public R redisPublish(String message){
        Message msg = new Message();
        msg.setSendUser("admin");
        msg.setReciveUser("allUser");
        msg.setTitle(message);
        msg.setContent("这是测试消息内容");
        msg.setStatus("1");
        msg.setCreateTime(new Date());

        com.sync.utils.framework.entity.UserInfo userInfo = this.getLoginUser();
        logger.info("当前登录用户：{}",userInfo);


        messageUtil.sendMessage(CHANNEL,msg);
        return R.ok().data(message);
    }


    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping(value = "getAppList")
    public R getAppList(@RequestParam("appKey") String appKey){
        String key = "syncutils:app:info";
        AppInfo app = redisCache.hget(key, appKey);
        logger.info("app:{}",app);
        logger.info("appObj:{}",redisCache.hmget(key));
        String token = request.getHeader(HeaderConstants.X_TOKEN);

        TokenUtils.getTokenUser(token);
        logger.info(redisCache.hget("syncutils:app:info", "1002"));
        return R.ok().data(app);
    }

}
